#include <stdio.h>

#include <ctype.h>


//E -> TE' 

//E' -> +TE' | e

//T -> FT'

//T' -> *FT' | e

//F -> NUM | (E)

//FIRST(E) = {NUM, LEFTB}

//FIRST(E') = {PLUS, e}

//FIRST(T) = {NUM, LEFTB}

//FIRST(T') = {MULT, e}

//FIRST(F) = {NUM, LEFTB}

//FOLLOW(E) = {$, RIGHTB}

//FOLLOW(E') = {$, RIGHTB}

//FOLLOW(T) = {PLUS, RIGHTB, $}

//FOLLOW(T') = {PLUS, RIGHTB, $}

//FOLLOW(F) = {MULT, PLUS, RIGHTB, $}


enum TOKEN {PLUS, MULT, NUM, END, ERR, LEFTB, RIGHTB};

char lookahead;

enum TOKEN token;

int num;

int error = 0;

FILE *fp;


void lexical(FILE *fp);

int match(enum TOKEN x);

int E();
int E_();

int T();

int T_();

int F();



//return 0 if success, return 1 otherwise

int match(enum TOKEN x) 
{
	if(token == x) 
        {
	
        	lexical(fp);

		return 0;

	}
        else
       {

		error = 1;

		return 1;

	}

}


//E -> TE'
 
int E()
 {

         switch(token)

	 {

	 case NUM:

	 case LEFTB:

	   return T()+E_();

	 default:

	   error=1;

	   return 1;
	  }

	 
}


//E_ -> +TE'|e
 
int E_()
 {

        switch(token)

	{

	 case PLUS:

	   match(token);

	   return T()+E_();

	 case RIGHTB:

	    return 0;

	 case END:

	  return 0;

	 default:

	  error=1;

	  return 1;

	}

           
}


//T -> FT'

int T()
{

        switch(token)

	{

	case NUM:

	case LEFTB:

	  return F()*T_();

        default:

	 error=1;

	 return 1;

	} 

	
}



//T' -> *FT' | e

int T_()
{ 
     switch(token)

	{

	 case MULT:

	  match(token);
	
          return F()*T_();

	 case PLUS:

         case RIGHTB:

	   return 1;

	 case END:

	  return 1;

	 default:

	  error=1;

	  return 1;

	}

      }

//F -> NUM | (E)

int F()
 {

        switch(token)

	{

	case NUM:

          if(!match(token))

	    {return num;}

	case LEFTB:

	  match(token);

	  int temp;

	  temp=E();

          match(token);

          return temp;

	case END:

	 return 1;

	default:

	 error=1;

	 return 1;

	}

       }

void lexical(FILE *fp)
 {


	lookahead = getc(fp);

	//num = 0;


	while(lookahead == ' ' || lookahead == '\t' || lookahead == '\n')
       {

		lookahead = getc(fp);

	}


	if(isdigit(lookahead))
        {

	        num=0;

		while(isdigit(lookahead))
                {

			token = NUM;

			num = num * 10 + lookahead - '0';

			lookahead = getc(fp);

		}

		ungetc(lookahead, fp);

		return;

	}
        else if(lookahead == '+')
       {

		token = PLUS;

		return;

	}
       else if (lookahead == '*')
       {

		token = MULT;

		return;

	}
        else if(lookahead == EOF)
       {

		token = END;

		return;

	}
        else if(lookahead == '(')
       {
		token = LEFTB;
		return;
	}
      else if(lookahead == ')') {
		token = RIGHTB;
		return;
	}
      else
     {

		error = 1;

		token = ERR;

		return;

	}

}


int main(int argc, char **argv)
 {

	int  res = 0;

	if(argc < 2)
        {

		printf("insufficient arguments");

		return 1;
   
	}

	fp = fopen(argv[1], "r");


	lexical(fp);

	res = E();

	if(!error)
        {
		printf("%d\n", res);
	}
       else {
		printf("There are errors\n");
	}

	
fclose(fp);

	return 0;


}
